package com.techbh.ridecall;

import java.util.prefs.Preferences;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;

/* TODO Dúvidas: como iniciar uma activity a partir do broadcastreceiver ?
 * 
 * */

public class ProximityAlertReceiver extends BroadcastReceiver {

	//Pode-se usar o getClass().getSimpleName() no lugar do APPTAG 
	private String APPTAG = "RideCall ProximityAlertReceiver";

	private static final int NOTIFICATION_ID = 1017;

	//Vou usar para detectar se pode ligar 
	private TelephonyManager telephony;

	private NotificationManager notificationManager;

	private SharedPreferences config;

	@Override
	public void onReceive(Context context, Intent intent) {
		Log.i(APPTAG, "onReceiver" );

		//Esse componente deve terminar o mais rápido possível 
		String action = intent.getAction();
		String scheme = intent.getScheme();
		String data = "";
		String dataauth = "";
		String msg_notificacao = "";
		String carona = "";	//TODO carona deve ser o nome ou o telefone (mascarado para boa leitura)
		int flags = intent.getFlags();
		Uri uridata = null;
		boolean aproximando = false;
		boolean chamar = false;
		boolean enviar_sms = false;
		Bundle extras = intent.getExtras();

		//Verifica o tipo de data
		try {
			uridata = intent.getData();
			data = uridata.toString();
			dataauth = uridata.getAuthority();
		} catch (NullPointerException e){
			//Não há Uri data no intent
		}

		//??? Previne que o mesmo seja passado para outras funções
		abortBroadcast();

		aproximando = intent.getBooleanExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);


		Log.i(APPTAG, "------------------------------------------------------");
		Log.i(APPTAG, "Alerta de proximidade recebido! " + data );
		Log.i(APPTAG, "- Action: " + action );
		Log.i(APPTAG, "- Data: " + data );
		Log.i(APPTAG, "- Scheme: " + scheme );
		Log.i(APPTAG, "- Data authority: " + dataauth );
		Log.i(APPTAG, "- Intent null: " + (intent == null) );
		Log.i(APPTAG, "- Esta aproximando: " + (aproximando) );
		Log.i(APPTAG, "- Flags: " + (flags) );
		Log.i(APPTAG, "------------------------------------------------------");

		//Não me lembro pra que pus isso, e também não sei pra que serve
		//tinha algo a ver com os testes e depuração
		/*
		synchronized (this) {
			notify();
		}
		 */

		//Não preciso avaliar se está saindo da área de interesse
		if(!aproximando){
			Log.d(APPTAG, "O usuário está saindo do ponto de interesse, não será feita a ligação" );
			//TODO no futuro pode-se ter uma opção apropriada 
			return;		
		}		

		//Gerenciador do "telefone"
		telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

		carona = data.substring(4);

		if( uridata == null ){
			//não tem informação pra tratar
			Log.d(APPTAG, "Não há informações pra tratar..." );
			return ;
		}
		
		msg_notificacao = "As mensagens não foram configuradas";

		//Toast.makeText(context, "Alerta de proximidade valido recebido! " + data, Toast.LENGTH_SHORT).show();

		if( action.equals("PROXIMITY_ALERT_CALL") ){
			Log.d(APPTAG, "PROXIMITY_ALERT_CALL reconhecida..." );
			chamar = true;
			msg_notificacao = "A chamada para " + carona + " foi feita";

		} else if( action.equals("PROXIMITY_ALERT_SMS") ){
			Log.d(APPTAG, "PROXIMITY_ALERT_SMS reconhecida..." );
			enviar_sms = true;
			msg_notificacao = "O sms foi enviado para " + carona + " ";

		} else if( action.equals("PROXIMITY_ALERT_CALL_SMS") ){
			Log.d(APPTAG, "PROXIMITY_ALERT_CALL_SMS reconhecida..." );
			chamar = true;
			enviar_sms = true;
			msg_notificacao = " " + carona + " foi alertado com chamada e sms";
		}

		if(enviar_sms){
			Log.d(APPTAG, "Vai enviar o sms..." );
			//config.getString("cfg_texto_sms", "Estou chegando...");
			String msg = extras.getString("msg");
			trataEnvioSMS(context, uridata.toString(), msg);
		}

		if(chamar){
			Log.d(APPTAG, "Vai testar se pode fazer a chamada..." );
			if(podeLigar(context)){
				Log.d(APPTAG, "Pode ligar para (" + carona + ") pois o telefone está disponível!" );

				Log.d(APPTAG, "Vai fazer a chamada..." );
				trataChamada(context, intent);

				//msg_notificacao = "Seu carona (" + carona + ") foi avisado!";//ajustado anteriormente
			} else {
				Log.d(APPTAG, "Não pode ligar para (" + carona + ") pois já está em outra ligação!" );
				//Mostra notificação apropriada

				msg_notificacao = "Não foi possível alertar (" + carona + ")!";
			}
		}


		//Gera uma notificação da ação
		notificationManager = 
			(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

		PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, null, 0);		

		Notification notification = criaNotificacao();
		notification.setLatestEventInfo(context, "RideCall", msg_notificacao, pendingIntent);
		notificationManager.notify(NOTIFICATION_ID, notification);
		
		
		//
		Notificador notificador = new Notificador(context);
		notificador.informaExecucaoAlerta(carona, extras);

	}

	//TODO verificar o estado do telefone antes de pedir uma chamada
	//TODO mudar retorno pra indicar se conseguiu ou não fazer chamada
	public void trataChamada(Context context, Intent i){
		Log.i(APPTAG, "trataChamada" );

		//Verifica os dados necessários para gerar o intent apropriado
		//gera a ação apropriada
		//lembrando que o broadcast deve retornar o mais rápido possível

		Uri tel_chamar = i.getData();

		Intent ic = new Intent(Intent.ACTION_CALL);
		ic.setData( tel_chamar );	
		ic.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		context.startActivity(ic);

	}


	private Notification criaNotificacao() {
		Notification notification = new Notification();

		notification.icon = R.drawable.ic_tel;
		notification.when = System.currentTimeMillis();

		notification.flags |= Notification.FLAG_AUTO_CANCEL;
		notification.flags |= Notification.FLAG_SHOW_LIGHTS;

		notification.defaults |= Notification.DEFAULT_VIBRATE;
		notification.defaults |= Notification.DEFAULT_LIGHTS;

		notification.ledARGB = Color.WHITE;
		notification.ledOnMS = 1500;
		notification.ledOffMS = 1500;

		return notification;
	}	


	public boolean podeLigar(Context ct){
		telephony = (TelephonyManager) ct.getSystemService(Context.TELEPHONY_SERVICE);
		int estado = telephony.getCallState();

		switch(estado){
		case TelephonyManager.CALL_STATE_IDLE:
			Log.d(APPTAG, "Estado do telefone: Disponível");
			return true;
		case TelephonyManager.CALL_STATE_OFFHOOK:
			Log.d(APPTAG, "Estado do telefone: Fora do gancho");
			return false;
		case TelephonyManager.CALL_STATE_RINGING:
			Log.d(APPTAG, "Estado do telefone: Chamando...");
			return false;
		}
		return false;	    
	}	


	public void trataEnvioSMS(Context ct, String numero, String mensagem ){
		SmsManager smsMg = SmsManager.getDefault();
		
		Log.d(APPTAG, "Vai enviar SMS para (" + numero + "): " + mensagem );
		boolean sair  = false;
		if(sair){
			Log.d(APPTAG, "Não vai enviar o SMS" );
			return ;
		}

		//Envia direto sem mostrar tela de edição
		PendingIntent pi = null;                

		String scAddress = null;	//service center address
		PendingIntent deliveryIntent = null;//será broadcasted quando o destinatario receber o sms
		smsMg.sendTextMessage(numero, scAddress, mensagem, pi, deliveryIntent);

	}

}
